package utils;

import static com.github.phantomthief.util.MoreFunctions.catching;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;

import org.apache.commons.lang3.tuple.Pair;

import javax.imageio.stream.ImageOutputStream;


import org.springframework.util.StopWatch;

import com.github.phantomthief.util.MoreFunctions;

/**
 * @author jiangfeng on 2022/7/7
 */
public class ImageUtils {

    public static final String PNG = "png";
    public static final String JPG = "jpg";
    public static final String JPEG = "jpeg";
    /**
     * 压缩率
     */
    public static final Float PICTURE_COMPRESS_RATIO = 0.5F;
    /**
     * 大于1M就压缩
     */
    public static final Integer COMPRESSED_COMPANY_ICON_MAX_SIZE = 1024 * 1024;
    // 图片是否为png的魔数判断, 只用前四位
    private static final byte PNG_FIRST_BYTE = (byte) 0x89;
    private static final byte PNG_SECOND_BYTE = (byte) 0x50;
    private static final byte PNG_THIRD_BYTE = (byte) 0x4E;
    private static final byte PNG_FORTH_BYTE = (byte) 0x47;
    // 图片是否为jpg的魔数判断, 只用前两位
    private static final byte JPG_FIRST_BYTE = (byte) 0xFF;
    private static final byte JPG_SECOND_BYTE = (byte) 0xD8;

    public static boolean isPng(byte[] bytes) {
        if (bytes.length > 4) {
            // 只检查前四位魔数是否对得上
            return bytes[0] == PNG_FIRST_BYTE
                    && bytes[1] == PNG_SECOND_BYTE
                    && bytes[2] == PNG_THIRD_BYTE
                    && bytes[3] == PNG_FORTH_BYTE;
        }
        return false;
    }

    public static boolean isJPG(byte[] bytes) {
        if (bytes.length > 2) {
            // 只检查前两位魔数是否对得上
            return bytes[0] == JPG_FIRST_BYTE
                    && bytes[1] == JPG_SECOND_BYTE;
        }
        return false;
    }

    public static Pair<byte[], BufferedImage> cropIfNecessary(BufferedImage image, byte[] picData, String format) {
        if (image.getHeight() == image.getWidth()) {
            return Pair.of(picData, image);
        }
        int edgeLength = Math.min(image.getHeight(), image.getWidth());

        int x = (image.getWidth() - edgeLength) / 2;
        int y = (image.getHeight() - edgeLength) / 2;

        //StopWatch watcher = PerfUtils.getWatcher();
        //watcher.start();
        BufferedImage croppedImage = image.getSubimage(x, y, edgeLength, edgeLength);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        catching(() -> ImageIO.write(croppedImage, format, outputStream));
        byte[] output = outputStream.toByteArray();
        return Pair.of(output, croppedImage);
    }

    public static byte[] compressPicIfNecessary(BufferedImage image, byte[] cropedData, String format) {
        if (cropedData.length <= COMPRESSED_COMPANY_ICON_MAX_SIZE) {
            return cropedData;
        }
        //StopWatch watcher = new StopWatch();
        //watcher.start();
        ImageWriter jpgWriter = ImageIO.getImageWritersByFormatName(format).next();
        ImageWriteParam jpgWriteParam = jpgWriter.getDefaultWriteParam();
        jpgWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        jpgWriteParam.setCompressionQuality(PICTURE_COMPRESS_RATIO);
        ByteArrayOutputStream compressed = new ByteArrayOutputStream();
        ImageOutputStream outputStream = MoreFunctions.catching(() -> ImageIO.createImageOutputStream(compressed));
        jpgWriter.setOutput(outputStream);

        MoreFunctions.runCatching(() -> jpgWriter.write(null, new IIOImage(image, null, null), jpgWriteParam));
        // Dispose the writer to free resources
        jpgWriter.dispose();
        byte[] output = compressed.toByteArray();
        return output;
    }
}
